<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><title>经典 JavaScript 手撕面试题 | Cyan</title><meta name="author" content="Cyan,843348394@qq.com"><meta name="copyright" content="Cyan"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="前言最近裁员找工作，在此记录一下面试中常见的手写函数实现，每天闲时不定时更新。   防抖函数12345678910111213141516171819202122232425262728293031323334353637383940414243&#x2F;** * 实现函数的防抖（目的是频繁触发中只执行最后一次） * @param &amp;#123;*&amp;#125; callback 需要执行的函数 * @par"><meta property="og:type" content="article"><meta property="og:title" content="经典 JavaScript 手撕面试题"><meta property="og:url" content="https://xmwpro.com/post/2610edc0.html"><meta property="og:site_name" content="Cyan"><meta property="og:description" content="前言最近裁员找工作，在此记录一下面试中常见的手写函数实现，每天闲时不定时更新。   防抖函数12345678910111213141516171819202122232425262728293031323334353637383940414243&#x2F;** * 实现函数的防抖（目的是频繁触发中只执行最后一次） * @param &amp;#123;*&amp;#125; callback 需要执行的函数 * @par"><meta property="og:locale" content="zh_CN"><meta property="og:image" content="https://ali-oss.xmwpro.com/global/avatar.jpg"><meta property="article:published_time" content="2022-08-02T13:36:14.000Z"><meta property="article:modified_time" content="2023-06-26T09:26:36.564Z"><meta property="article:author" content="Cyan"><meta property="article:tag" content="JavaScript"><meta property="article:tag" content="面试"><meta name="twitter:card" content="summary"><meta name="twitter:image" content="https://ali-oss.xmwpro.com/global/avatar.jpg"><link rel="shortcut icon" href="https://ali-oss.xmwpro.com/global/favicon.ico"><link rel="canonical" href="https://xmwpro.com/post/2610edc0.html"><link rel="preconnect" href="//cdn.jsdelivr.net"><link rel="preconnect" href="//www.google-analytics.com" crossorigin=""><link rel="preconnect" href="//hm.baidu.com"><meta name="baidu-site-verification" content="codeva-yHszJZWbvj"><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/all.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/snackbar.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/fancybox.css" media="print" onload='this.media="all"'><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?81fae81fdc8992b3e6ca314f289131e8";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script async src="https://www.googletagmanager.com/gtag/js?id=G-2P0LMHZNDD"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-2P0LMHZNDD")</script><script>const GLOBAL_CONFIG={root:"/",algolia:{appId:"2Q4I5JDAJR",apiKey:"2ec9f676fd9c568eb0abedad38d16fe6",indexName:"Hexo",hits:{per_page:6},languages:{input_placeholder:"输入关键词快速查找",hits_empty:"找不到您查询的内容：${query}",hits_stats:"找到 ${hits} 条结果，用时 ${time} 毫秒"}},localSearch:void 0,translate:{defaultEncoding:2,translateDelay:0,msgToTraditionalChinese:"繁",msgToSimplifiedChinese:"簡"},noticeOutdate:void 0,highlight:{plugin:"highlighjs",highlightCopy:!0,highlightLang:!0,highlightHeightLimit:200},copy:{success:"复制成功",error:"复制错误",noSupport:"浏览器不支持"},relativeDate:{homepage:!1,post:!1},runtime:"天",date_suffix:{just:"刚刚",min:"分钟前",hour:"小时前",day:"天前",month:"个月前"},copyright:{limitCount:50,languages:{author:"作者: Cyan",link:"链接: ",source:"来源: Cyan",info:"著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"}},lightbox:"fancybox",Snackbar:{chs_to_cht:"你已切换为繁体",cht_to_chs:"你已切换为简体",day_to_night:"你已切换为深色模式",night_to_day:"你已切换为浅色模式",bgLight:"var(--cyan-theme-color)",bgDark:"var(--cyan-theme-color)",position:"top-center"},source:{justifiedGallery:{js:"https://ali-oss.xmwpro.com/cdn/js/fjGallery.min.js",css:"https://ali-oss.xmwpro.com/cdn/css/fjGallery.css"}},isPhotoFigcaption:!0,islazyload:!0,isAnchor:!1,percent:{toc:!1,rightside:!0}}</script><script id="config-diff">var GLOBAL_CONFIG_SITE={title:"经典 JavaScript 手撕面试题",isPost:!0,isHome:!1,isHighlightShrink:!1,isToc:!0,postUpdate:"2023-06-26 09:26:36"}</script><noscript><style>#nav{opacity:1}.justified-gallery img{opacity:1}#post-meta time,#recent-posts time{display:inline!important}</style></noscript><script>(e=>{e.saveToLocal={set:function(e,t,o){if(0===o)return;const n=864e5*o,a={value:t,expiry:(new Date).getTime()+n};localStorage.setItem(e,JSON.stringify(a))},get:function(e){const t=localStorage.getItem(e);if(!t)return;const o=JSON.parse(t);if(!((new Date).getTime()>o.expiry))return o.value;localStorage.removeItem(e)}},e.getScript=e=>new Promise(((t,o)=>{const n=document.createElement("script");n.src=e,n.async=!0,n.onerror=o,n.onload=n.onreadystatechange=function(){const e=this.readyState;e&&"loaded"!==e&&"complete"!==e||(n.onload=n.onreadystatechange=null,t())},document.head.appendChild(n)})),e.getCSS=e=>new Promise(((t,o)=>{const n=document.createElement("link");n.rel="stylesheet",n.href=e,n.onload=()=>t(),n.onerror=()=>o(),document.head.appendChild(n)})),e.activateDarkMode=function(){document.documentElement.setAttribute("data-theme","dark"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#0d0d0d")},e.activateLightMode=function(){document.documentElement.setAttribute("data-theme","light"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#ffffff")};const t=saveToLocal.get("theme"),o=(new Date).getHours();void 0===t?o<=6||o>=18?activateDarkMode():activateLightMode():"light"===t?activateLightMode():activateDarkMode();const n=saveToLocal.get("aside-status");void 0!==n&&("hide"===n?document.documentElement.classList.add("hide-aside"):document.documentElement.classList.remove("hide-aside"));/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)&&document.documentElement.classList.add("apple")})(window)</script><link rel="stylesheet" href="//at.alicdn.com/t/c/font_3348168_pqjhlyxfz9r.css" media="defer" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/swiper-bundle.min.css"><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/tianli_gpt.css"><script src="https://ali-oss.xmwpro.com/cdn/js/swiper-bundle.min.js"></script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/jquery-3.3.1.js"></script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/echarts.min.js"></script><script charset="UTF-8" id="LA_COLLECT" src="https://sdk.51.la/js-sdk-pro.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/three.min.js"></script><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/font-awesome-animation.min.css" media="defer" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/tag_plugins.css" media="defer" onload='this.media="all"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/animate.min.css" media="print" onload='this.media="screen"'><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/gitcalendar.css" media="print" onload='this.media="all"'><meta name="generator" content="Hexo 5.4.2"><link rel="alternate" href="/atom.xml" title="Cyan" type="application/atom+xml"></head><body><div id="loading-box" onclick="document.getElementById(&quot;loading-box&quot;).classList.add(&quot;loaded&quot;)"><div class="loading-bg"><div class="loading-img"></div><div class="loading-image-dot"></div></div></div><script>const preloader={endLoading:()=>{document.body.style.overflow="auto",document.getElementById("loading-box").classList.add("loaded")},initLoading:()=>{document.body.style.overflow="",document.getElementById("loading-box").classList.remove("loaded")}};window.addEventListener("load",(()=>{preloader.endLoading()})),document.addEventListener("pjax:send",(()=>{preloader.initLoading()})),document.addEventListener("pjax:complete",(()=>{preloader.endLoading()}))</script><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/progress_bar.css"><script src="https://ali-oss.xmwpro.com/cdn/js/pace.min.js"></script><div id="web_bg"></div><div id="music_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/avatar.jpg" onerror='onerror=null,src="/img/friend_404.gif"' alt="avatar"></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">48</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">23</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">6</div></a></div><hr><div class="menus_items"><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fas fa-book"></i> <span>文库</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><i class="fa-fw faa-tada fa-solid fa-box-archive"></i> <span>全部文章</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><i class="fa-fw faa-tada fas fa-tags"></i> <span>标签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><i class="fa-fw faa-tada fas fa-shapes"></i> <span>分类</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fab fa-artstation"></i> <span>社交</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/link/"><i class="fa-fw faa-tada fa-solid fa-link"></i> <span>友人帐</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/fcircle/"><i class="fa-fw faa-tada fa-solid fa-user-group"></i> <span>朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/guestbook/"><i class="fa-fw faa-tada fa-solid fa-envelope"></i> <span>留言板</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fas fa-coffee"></i> <span>休闲</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/music/"><i class="fa-fw faa-tada fa-solid fa-music"></i> <span>音乐馆</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/photoAlbum/"><i class="fa-fw faa-tada fa-solid fa-camera"></i> <span>相册</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/essay/"><i class="fa-fw faa-tada fa-solid fa-message"></i> <span>哔哔</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fa-solid fa-earth-asia"></i> <span>本站</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/analysis/"><i class="fa-fw faa-tada fa-solid fa-chart-simple"></i> <span>博客统计</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/about/"><i class="fa-fw faa-tada fa-regular fa-address-card"></i> <span>关于我</span></a></li></ul></div></div></div></div><div class="canvas-container" id="canvas"></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image:url('https://ali-oss.xmwpro.com/posts/post_cover11.jpg')"><nav id="nav"><span id="blog-info"><div class="back-home-button" tabindex="-1"><i class="back-home-button-icon fas fa-grip-vertical"></i><div class="back-menu-list-groups"><div class="back-menu-list-group"><div class="back-menu-list-title">社交</div><div class="back-menu-list"><a class="back-menu-item" href="https://xmwpro.com/" title="白雾茫茫丶" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/global/avatar.jpg"><span class="back-menu-item-text">白雾茫茫丶</span></a><a class="back-menu-item" href="https://github.com/Cyan-Xmw/" rel="external nofollow noreferrer" title="Github" target="_blank" one-link-mark="yes"><i class="iconfont cyan-gitHub"></i><span class="back-menu-item-text">Github</span></a><a class="back-menu-item" href="https://gitee.com/Cyan-Xmw/" rel="external nofollow noreferrer" title="Gitee" target="_blank" one-link-mark="yes"><i class="iconfont cyan-gitee"></i><span class="back-menu-item-text">Gitee</span></a><a class="back-menu-item" href="https://juejin.cn/user/1917147257534279/" rel="external nofollow noreferrer" title="掘金" target="_blank" one-link-mark="yes"><i class="iconfont cyan-juejin"></i><span class="back-menu-item-text">掘金</span></a></div></div><div class="back-menu-list-group"><div class="back-menu-list-title">项目</div><div class="back-menu-list"><a class="back-menu-item" href="https://docs.xmwpro.com/" rel="external nofollow noreferrer" title="Cyan Docs" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/project/xmw-dumi-docs/logo.svg"><span class="back-menu-item-text">Cyan Docs</span></a><a class="back-menu-item" href="http://react.xmwpro.com/" rel="external nofollow noreferrer" title="Xmw-Admin" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/pages/resource/xmw-admin.svg"><span class="back-menu-item-text">Xmw-Admin</span></a><a class="back-menu-item" href="http://vue3.xmwpro.com/" rel="external nofollow noreferrer" title="Vue3-Admin" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/project/vue3-admin/logo.png"><span class="back-menu-item-text">Vue3-Admin</span></a><a class="back-menu-item" href="http://vue2.xmwpro.com/" rel="external nofollow noreferrer" title="Vue2-Admin" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/project/vue2-admin/logo.svg"><span class="back-menu-item-text">Vue2-Admin</span></a><a class="back-menu-item" href="https://ele-plus-form.xmwpro.com/" rel="external nofollow noreferrer" title="vue3-form" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/pages/resource/vue.svg"><span class="back-menu-item-text">vue3-form</span></a><a class="back-menu-item" href="https://ele-plus-table.xmwpro.com/" rel="external nofollow noreferrer" title="vue3-table" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="" data-lazy-src="https://ali-oss.xmwpro.com/pages/resource/vue.svg"><span class="back-menu-item-text">vue3-table</span></a></div></div></div></div><a id="site-name" href="/"><div class="title">Cyan</div><i class="fa-solid fa-house"></i></a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fas fa-book"></i> <span>文库</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><i class="fa-fw faa-tada fa-solid fa-box-archive"></i> <span>全部文章</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><i class="fa-fw faa-tada fas fa-tags"></i> <span>标签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><i class="fa-fw faa-tada fas fa-shapes"></i> <span>分类</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fab fa-artstation"></i> <span>社交</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/link/"><i class="fa-fw faa-tada fa-solid fa-link"></i> <span>友人帐</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/fcircle/"><i class="fa-fw faa-tada fa-solid fa-user-group"></i> <span>朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/guestbook/"><i class="fa-fw faa-tada fa-solid fa-envelope"></i> <span>留言板</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fas fa-coffee"></i> <span>休闲</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/music/"><i class="fa-fw faa-tada fa-solid fa-music"></i> <span>音乐馆</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/photoAlbum/"><i class="fa-fw faa-tada fa-solid fa-camera"></i> <span>相册</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/essay/"><i class="fa-fw faa-tada fa-solid fa-message"></i> <span>哔哔</span></a></li></ul></div><div class="menus_item"><a class="site-page group faa-parent animated-hover" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fa-fw faa-tada fa-solid fa-earth-asia"></i> <span>本站</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/analysis/"><i class="fa-fw faa-tada fa-solid fa-chart-simple"></i> <span>博客统计</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/about/"><i class="fa-fw faa-tada fa-regular fa-address-card"></i> <span>关于我</span></a></li></ul></div></div><center id="name-container"><span id="page-name" href="javascript:void(0);">PAGE_NAME</span></center></div><div id="nav-right"><div class="nav-button" id="search-button"><a class="social-icon search" href="javascript:void(0);" rel="external nofollow noreferrer" title="全局搜索"><i class="fas fa-search fa-fw"></i></a></div><div class="nav-button"><a class="social-icon" target="_blank" rel="noopener external nofollow noreferrer" href="https://travellings.cn/go.html" title="离开这里并访问下一个博客「开往服务」"><i class="fa-solid fa-subway"></i></a></div><div class="nav-button"><a class="social-icon random-post" href="javascript:toRandomPost();" rel="external nofollow noreferrer" title="随机前往一个文章"><i class="fa-solid fa-dice"></i></a></div><div class="nav-button" id="darkmode_navswitch"><a class="darkmode_switchbutton" type="button" title="浅色和深色模式转换" onclick="document.getElementById(&quot;darkmode&quot;).click()"><i class="fas fa-moon isMoon"></i><i class="fas fa-sun isSun"></i></a></div><div class="nav-button" id="go-up" title="回到顶部"><a class="totopbtn" href="javascript:void(0);" rel="external nofollow noreferrer"><span class="scroll-percent" onclick="btf.scrollToDest(0,500)"></span><i class="fas fa-arrow-up" onclick="btf.scrollToDest(0,500)"></i></a></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><div class="post-container"><div class="post-container-categories"><a class="categories-link" href="/categories/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/">前端开发</a></div><div class="post-container-tags"><a class="tags-link" href="/tags/JavaScript/"><span class="tags-punctuation">#</span><span class="tags-name">JavaScript</span></a><a class="tags-link" href="/tags/%E9%9D%A2%E8%AF%95/"><span class="tags-punctuation">#</span><span class="tags-name">面试</span></a></div></div><h1 class="post-title">经典 JavaScript 手撕面试题</h1><div id="post-meta"><div class="meta-secondline"><div class="post-meta-common post-meta-date" title="发表于 2022-08-02 13:36:14"><i class="fas fa-calendar fa-fw post-meta-icon"></i><time class="post-meta-date-created" datetime="2022-08-02T13:36:14.000Z">08-02</time></div><div class="post-meta-common post-meta-date" title="更新于 2023-06-26 09:26:36"><i class="fas fa-history fa-fw post-meta-icon"></i><time class="post-meta-date-updated" datetime="2022-08-02T13:36:14.000Z">06-26</time></div><div class="post-meta-common post-meta-wordcount" title="字数总计 4.6k"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="word-count">4.6k</span></div><div class="post-meta-common post-meta-read-time" title="阅读时长 20分钟"><i class="far fa-clock fa-fw post-meta-icon"></i><span>20分钟</span></div><div class="post-meta-common post-meta-commentcount" title="评论数" onclick='cyan.scrollTo("#post-comment")'><i class="fa-solid fa-comment fa-fw post-meta-icon"></i><a href="/post/2610edc0.html#post-comment"><span id="twikoo-count"><i class="fa-solid fa-spinner fa-spin"></i></span></a></div></div></div></div><section class="main-hero-waves-area waves-area"><svg class="waves-svg" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s58 18 88 18 58-18 88-18 58 18 88 18v44h-352Z"></path></defs><g class="parallax"><use href="#gentle-wave" x="48" y="0"></use><use href="#gentle-wave" x="48" y="3"></use><use href="#gentle-wave" x="48" y="5"></use><use href="#gentle-wave" x="48" y="7"></use></g></svg></section></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><div class="tip theme fa-house"><p>最近裁员找工作，在此记录一下面试中常见的手写函数实现，每天闲时不定时更新。</p></div><h2 id="防抖函数"><a href="#防抖函数" class="headerlink" title="防抖函数"></a>防抖函数</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现函数的防抖（目的是频繁触发中只执行最后一次）</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback 需要执行的函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; delay 检测防抖的间隔频率，默认500ms</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; immediate 是否是立即执行 true：第一次，false：最后一次，默认false</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="type">可被调用执行的函数</span>&#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">debounce</span> = (<span class="params">callback, delay = <span class="number">500</span>, immediate = <span class="literal">false</span></span>) =&gt; &#123;</span><br><span class="line">    <span class="comment">// 声明一个定时器容器</span></span><br><span class="line">    <span class="keyword">let</span> timer = <span class="literal">null</span></span><br><span class="line">    <span class="comment">// isImmediateInvoke变量用来记录是否立即执行, 默认为false</span></span><br><span class="line">    <span class="keyword">let</span> isImmediateInvoke = <span class="literal">false</span></span><br><span class="line">    <span class="comment">// 判断callback是否为一个函数</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;callback is not a function&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">_debounce</span> = (<span class="params">...args</span>) =&gt; &#123;</span><br><span class="line">        <span class="comment">// 保存上下文的this指向</span></span><br><span class="line">        <span class="keyword">let</span> context = <span class="variable language_">this</span></span><br><span class="line">        <span class="comment">// 判断定时器是否存在，存在则清空定时器重新开启</span></span><br><span class="line">        timer &amp;&amp; <span class="built_in">clearTimeout</span>(timer)</span><br><span class="line">        <span class="comment">// 判断是否第一次触发</span></span><br><span class="line">        <span class="keyword">if</span> (!isImmediateInvoke &amp;&amp; immediate) &#123;</span><br><span class="line">            <span class="comment">// 改变callback函数的this指向</span></span><br><span class="line">            callback.<span class="title function_">apply</span>(context, args)</span><br><span class="line">            <span class="comment">// 将isImmediateInvoke设置为true，这样不会影响到后面函数的调用</span></span><br><span class="line">            isImmediateInvoke = <span class="literal">true</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            timer = <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">                <span class="comment">// 改变callback函数的this指向</span></span><br><span class="line">                callback.<span class="title function_">apply</span>(context, args)</span><br><span class="line">                <span class="comment">// 将isImmediateInvoke设置为false，这样下一次的第一次触发事件才能执行</span></span><br><span class="line">                isImmediateInvoke = <span class="literal">false</span></span><br><span class="line">            &#125;, delay)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 取消防抖函数功能</span></span><br><span class="line">    _debounce.<span class="property">cache</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">clearTimeout</span>(timer)</span><br><span class="line">        timer = <span class="literal">null</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> _debounce</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;button id=<span class="string">&quot;btn&quot;</span>&gt;点击&lt;/button&gt;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;点击按钮&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;#btn&#x27;</span>).<span class="title function_">addEventListener</span>(<span class="string">&#x27;click&#x27;</span>, <span class="title function_">debounce</span>(fn, <span class="number">1000</span>, <span class="literal">true</span>))</span><br></pre></td></tr></table></figure><h2 id="节流函数"><a href="#节流函数" class="headerlink" title="节流函数"></a>节流函数</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现函数的节流（目的是频繁触发中只执行一次）</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback 需要执行的函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; delay 检测防抖的间隔频率，默认500ms</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; immediate 是否是立即执行 true：第一次，false：最后一次，默认false</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="type">可被调用执行的函数</span>&#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">throttle</span> = (<span class="params">callback, delay = <span class="number">500</span>, immediate = <span class="literal">false</span></span>) =&gt; &#123;</span><br><span class="line">    <span class="comment">// 记录上一次执行时间</span></span><br><span class="line">    <span class="keyword">let</span> preTime = <span class="number">0</span></span><br><span class="line">    <span class="comment">// 判断callback是否为一个函数</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;callback is not a function&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="function">(<span class="params">...args</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// 保存上下文的this指向</span></span><br><span class="line">        <span class="keyword">let</span> context = <span class="variable language_">this</span>,</span><br><span class="line">            nowTime = +<span class="keyword">new</span> <span class="title class_">Date</span>(), <span class="comment">// 记录当前的时间</span></span><br><span class="line">            flag = nowTime - preTime &gt;= delay <span class="comment">// 执行命令</span></span><br><span class="line">        <span class="comment">// 如果flag为true，则不中断函数</span></span><br><span class="line">        <span class="keyword">if</span> (!flag) <span class="keyword">return</span></span><br><span class="line">        preTime = nowTime <span class="comment">// 更新执行时间</span></span><br><span class="line">        <span class="comment">// 判断是否第一次触发</span></span><br><span class="line">        immediate ? callback.<span class="title function_">apply</span>(context, args) : <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// 改变callback函数的this指向</span></span><br><span class="line">            callback.<span class="title function_">apply</span>(context, args)</span><br><span class="line">        &#125;, delay)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;button id=<span class="string">&quot;btn&quot;</span>&gt;点击&lt;/button&gt;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;点击按钮&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&#x27;#btn&#x27;</span>).<span class="title function_">addEventListener</span>(<span class="string">&#x27;click&#x27;</span>, <span class="title function_">throttle</span>(fn, <span class="number">1000</span>, <span class="literal">true</span>))</span><br></pre></td></tr></table></figure><h2 id="函数柯里化"><a href="#函数柯里化" class="headerlink" title="函数柯里化"></a>函数柯里化</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现函数的柯里化（把一个多参数的函数，转化为单参数函数）</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback 需要执行的函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="type">可被调用执行的函数</span>&#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// ES6箭头函数写法，简洁但可读性差</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment">调用curry函数，获取函数fn的参数。</span></span><br><span class="line"><span class="comment">定义一个新的函数judge，接收参数为...args。</span></span><br><span class="line"><span class="comment">判断新函数接受的参数长度是否大于等于fn剩余参数需要接收的长度</span></span><br><span class="line"><span class="comment">满足要求，则执行fn函数，并传入新函数的参数</span></span><br><span class="line"><span class="comment">否则，返回一个新的匿名函数，这个函数把所有传入参数...args保存在arg数组中，而这个匿名函数被执行后，就把以前收到的参数数组和当前的参数数组合并后，放到前面说的逻辑中，在judge函数里判断，重复第3步。</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">curry</span> = callback =&gt; judge = <span class="function">(<span class="params">...args</span>) =&gt;</span> args.<span class="property">length</span> &gt;= callback.<span class="property">length</span> ? <span class="title function_">callback</span>(...args) : <span class="function">(<span class="params">...args2</span>) =&gt;</span> <span class="title function_">judge</span>(...args, ...args2)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 常规写法，可读性好</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">curry</span> = callback =&gt; &#123;</span><br><span class="line">    <span class="comment">// 判断callback是否为一个函数</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;callback is not a function&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> judge = <span class="function">(<span class="params">...args</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (args.<span class="property">length</span> &gt;= callback.<span class="property">length</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="title function_">callback</span>(...args)</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="function">(<span class="params">...args2</span>) =&gt;</span> &#123;</span><br><span class="line">                <span class="keyword">return</span> <span class="title function_">judge</span>(...args, ...args2)</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">add</span>(<span class="params">a, b, c</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> a + b + c</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> addCurry = <span class="title function_">curry</span>(add)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">addCurry</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>)) <span class="comment">// 6</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">addCurry</span>(<span class="number">1</span>, <span class="number">2</span>)(<span class="number">3</span>)) <span class="comment">// 6</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">addCurry</span>(<span class="number">1</span>)(<span class="number">2</span>)(<span class="number">3</span>)) <span class="comment">// 6</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">addCurry</span>(<span class="number">1</span>)(<span class="number">2</span>, <span class="number">3</span>)) <span class="comment">// 6</span></span><br></pre></td></tr></table></figure><h2 id="深拷贝"><a href="#深拷贝" class="headerlink" title="深拷贝"></a>深拷贝</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现深克隆（针对JS的引用类型）</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; target 需要深克隆的数据</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> 返回克隆的对象</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//  递归使用Reflect.ownKeys实现</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">deepClone</span> = target =&gt; &#123;</span><br><span class="line">    <span class="comment">// 判断target是否是引用类型</span></span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">isObject</span> = target =&gt; <span class="keyword">typeof</span> target === <span class="string">&#x27;object&#x27;</span> &amp;&amp; target !== <span class="literal">null</span></span><br><span class="line">    <span class="keyword">if</span> (!isObject) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;Target is not a Object&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 判断target是数组还是对象</span></span><br><span class="line">    <span class="keyword">const</span> result = <span class="title class_">Array</span>.<span class="title function_">isArray</span>(target) ? [...target] : &#123; ...target &#125;</span><br><span class="line">    <span class="comment">// 使用Reflect.ownKeys递归遍历</span></span><br><span class="line">    <span class="title class_">Reflect</span>.<span class="title function_">ownKeys</span>(result).<span class="title function_">forEach</span>(<span class="function"><span class="params">key</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// 判断key是否是引用类型，deepClone递归</span></span><br><span class="line">        result[key] = <span class="title function_">isObject</span>(target[key]) ? <span class="title function_">deepClone</span>(target[key]) : target[key]</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> data = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&#x27;Cyan&#x27;</span>,</span><br><span class="line">    <span class="attr">age</span>: <span class="number">27</span>,</span><br><span class="line">    <span class="attr">desc</span>: &#123;</span><br><span class="line">        <span class="attr">jobs</span>: <span class="string">&#x27;前端开发&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> cloneData = <span class="title function_">deepClone</span>(data)</span><br><span class="line"></span><br><span class="line">data.<span class="property">name</span> = <span class="string">&#x27;白雾茫茫丶&#x27;</span></span><br><span class="line">data.<span class="property">desc</span>.<span class="property">jobs</span> = <span class="string">&#x27;后端开发&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(cloneData)</span><br></pre></td></tr></table></figure><h2 id="Instanceof-实现"><a href="#Instanceof-实现" class="headerlink" title="Instanceof 实现"></a>Instanceof 实现</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现instanceof（判断左侧对象是否是右侧构造函数的实例化对象）</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; _leftObj 左侧实例对象，_rightClass 右侧构造函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Boolean</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">_instanceof</span> = (<span class="params">_leftObj, _rightClass</span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">isObject</span> = target =&gt; (<span class="keyword">typeof</span> target === <span class="string">&#x27;object&#x27;</span> || <span class="keyword">typeof</span> target === <span class="string">&#x27;function&#x27;</span>) &amp;&amp; target !== <span class="literal">null</span></span><br><span class="line">    <span class="comment">// 判断参数类型，左侧必须为对象类型，右侧必须为函数类型</span></span><br><span class="line">    <span class="keyword">if</span> (!<span class="title function_">isObject</span>(_leftObj) || !<span class="title function_">isObject</span>(_rightClass)) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;Incorrect parameter type&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// Object.getPrototypeOf获取实例对象的原型和右侧构造函数的prototype对象</span></span><br><span class="line">    <span class="keyword">const</span> leftProto = <span class="title class_">Object</span>.<span class="title function_">getPrototypeOf</span>(_leftObj)</span><br><span class="line">    <span class="keyword">const</span> rightProto = _rightClass.<span class="property"><span class="keyword">prototype</span></span></span><br><span class="line">    <span class="comment">// 循环查找原型链</span></span><br><span class="line">    <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">        <span class="comment">// 找到Object原型链的顶端 Object.prototype.__proto__</span></span><br><span class="line">        <span class="keyword">if</span> (leftProto === <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 在当前实例对象的原型链上找到了实例类</span></span><br><span class="line">        <span class="keyword">if</span> (leftProto === rightProto) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 沿着原型链__ptoto__一层一层向上查找</span></span><br><span class="line">        leftProto = <span class="title class_">Object</span>.<span class="title function_">getPrototypeOf</span>(leftProto)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> dataA = [<span class="number">1</span>, <span class="number">2</span>]</span><br><span class="line"><span class="keyword">const</span> dataO = &#123; <span class="attr">name</span>: <span class="string">&#x27;Cyan&#x27;</span> &#125;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">_instanceof</span>(dataA, <span class="title class_">Array</span>))</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">_instanceof</span>(dataO, <span class="title class_">Object</span>))</span><br></pre></td></tr></table></figure><h2 id="Object-create-实现"><a href="#Object-create-实现" class="headerlink" title="Object.create 实现"></a>Object.create 实现</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现Object.create（Object.create()方法创建一个新对象，使用现有的对象来提供新创建的对象的__proto__）</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; prototype 新创建对象的原型对象 </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Object</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Object</span>.<span class="property">myCreate</span> = <span class="function">(<span class="params">prototype</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="title function_">isObject</span> = target =&gt; <span class="keyword">typeof</span> target === <span class="string">&#x27;object&#x27;</span> &amp;&amp; target !== <span class="literal">null</span></span><br><span class="line">    <span class="comment">// 判断prototype是否是对象</span></span><br><span class="line">    <span class="keyword">if</span> (!<span class="title function_">isObject</span>(prototype)) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;prototype is not a Object&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 内部声明一个构造函数</span></span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">Fn</span>(<span class="params"></span>) &#123; &#125;</span><br><span class="line">    <span class="comment">// 将构造函数的原型设置为prototype</span></span><br><span class="line">    <span class="title class_">Fn</span>.<span class="property"><span class="keyword">prototype</span></span> = prototype</span><br><span class="line">    <span class="comment">// 给Fn.prototype添加构造属性，使其不可枚举</span></span><br><span class="line">    <span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(<span class="title class_">Fn</span>.<span class="property"><span class="keyword">prototype</span></span>, <span class="string">&#x27;constructor&#x27;</span>, &#123;</span><br><span class="line">        <span class="attr">value</span>: <span class="title class_">Fn</span>,</span><br><span class="line">        <span class="attr">enumerable</span>: <span class="literal">false</span></span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Fn</span>()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">Person</span> = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&#x27;Cyan&#x27;</span>,</span><br><span class="line">    <span class="attr">sayName</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`我的名字是<span class="subst">$&#123;<span class="variable language_">this</span>.name&#125;</span>`</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> child = <span class="title class_">Object</span>.<span class="title function_">myCreate</span>(<span class="title class_">Person</span>)</span><br><span class="line">child.<span class="title function_">sayName</span>()</span><br></pre></td></tr></table></figure><h2 id="New-实现"><a href="#New-实现" class="headerlink" title="New 实现"></a>New 实现</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现new</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback 要操作的类（最后要创建这个类的实例）</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; args 存储未来传递给callback类的实参</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Object</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">_new</span> = (<span class="params">callback, ...args</span>) =&gt; &#123;</span><br><span class="line"><span class="comment">// //  创建一个空对象</span></span><br><span class="line"><span class="comment">// const obj = new Object()</span></span><br><span class="line"><span class="comment">// // 将obj的__proto__指向callback.prototype</span></span><br><span class="line"><span class="comment">// obj.__proto__ = callback.prototype</span></span><br><span class="line"><span class="comment">// IE环境不支持__proto__</span></span><br><span class="line"><span class="keyword">let</span> obj = <span class="title class_">Object</span>.<span class="title function_">create</span>(callback.<span class="property"><span class="keyword">prototype</span></span>)</span><br><span class="line"><span class="comment">// 将callback执行并改变this指向</span></span><br><span class="line"><span class="keyword">const</span> result = callback.<span class="title function_">call</span>(obj, ...args)</span><br><span class="line"><span class="comment">// 判断函数的返回值</span></span><br><span class="line"><span class="keyword">return</span> <span class="keyword">typeof</span> result === <span class="string">&#x27;object&#x27;</span> &amp;&amp; result !== <span class="literal">null</span> ? result : obj</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params">name, age</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">name</span> = name</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">age</span> = age</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> child = <span class="title function_">_new</span>(<span class="title class_">Person</span>, <span class="string">&#x27;Cyan&#x27;</span>, <span class="number">27</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(child)</span><br></pre></td></tr></table></figure><h2 id="手写-Bind"><a href="#手写-Bind" class="headerlink" title="手写 Bind"></a>手写 Bind</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现bind</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; ctx 传递的对象</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Function</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myBind</span> = <span class="keyword">function</span> (<span class="params">ctx</span>) &#123;</span><br><span class="line"><span class="comment">// 获取bind传递的剩余参数</span></span><br><span class="line"><span class="keyword">let</span> args = <span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">slice</span>.<span class="title function_">call</span>(<span class="variable language_">arguments</span>, <span class="number">1</span>)</span><br><span class="line"><span class="comment">// fn.bind中的fn</span></span><br><span class="line"><span class="keyword">const</span> fn = <span class="variable language_">this</span></span><br><span class="line"><span class="keyword">return</span> <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> fn.<span class="title function_">apply</span>(ctx, args)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params">name, age</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>, name, age)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> newFn = fn.<span class="title function_">myBind</span>(&#123;&#125;, <span class="string">&#x27;Cyan&#x27;</span>, <span class="number">27</span>)</span><br><span class="line"><span class="title function_">newFn</span>()</span><br></pre></td></tr></table></figure><h2 id="手写-Apply"><a href="#手写-Apply" class="headerlink" title="手写 Apply"></a>手写 Apply</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现apply</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; ctx 传递的对象</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; args[Array] 传递的参数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Function</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myApply</span> = <span class="keyword">function</span> (<span class="params">ctx, args</span>) &#123;</span><br><span class="line"><span class="comment">// 必须保证ctx是一个对象，如果是null或undefined，则指向全局，否则转化成对象</span></span><br><span class="line"><span class="comment">// 此处全局使用globalThis，是因为JS的运行环境有浏览器和node</span></span><br><span class="line">ctx = (ctx === <span class="literal">null</span> || ctx === <span class="literal">undefined</span>) ? globalThis : <span class="title class_">Object</span>(ctx)</span><br><span class="line"><span class="comment">// 使用Symbol，避免和ctx重名</span></span><br><span class="line"><span class="keyword">let</span> key = <span class="title class_">Symbol</span>(<span class="string">&#x27;fn&#x27;</span>)</span><br><span class="line"><span class="comment">// Object.defineProperty设置不可枚举</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(ctx, key, &#123;</span><br><span class="line">    <span class="attr">enumerable</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="attr">value</span>: <span class="variable language_">this</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 执行函数，并将执行的结果返回</span></span><br><span class="line"><span class="keyword">return</span> ctx[key](...args)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params">name, age</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>, name, age)</span><br><span class="line">&#125;</span><br><span class="line">fn.<span class="title function_">myApply</span>(&#123;&#125;, [<span class="string">&#x27;Cyan&#x27;</span>, <span class="number">27</span>])</span><br></pre></td></tr></table></figure><h2 id="手写-Call"><a href="#手写-Call" class="headerlink" title="手写 Call"></a>手写 Call</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现call</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; ctx 传递的对象</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; args 传递的参数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Function</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="title class_">Function</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myCall</span> = <span class="keyword">function</span> (<span class="params">ctx, ...args</span>) &#123;</span><br><span class="line"><span class="comment">// 必须保证ctx是一个对象，如果是null或undefined，则指向全局，否则转化成对象</span></span><br><span class="line"><span class="comment">// 此处全局使用globalThis，是因为JS的运行环境有浏览器和node</span></span><br><span class="line">ctx = (ctx === <span class="literal">null</span> || ctx === <span class="literal">undefined</span>) ? globalThis : <span class="title class_">Object</span>(ctx)</span><br><span class="line"><span class="comment">// 使用Symbol，避免和ctx重名</span></span><br><span class="line"><span class="keyword">let</span> key = <span class="title class_">Symbol</span>(<span class="string">&#x27;fn&#x27;</span>)</span><br><span class="line"><span class="comment">// Object.defineProperty设置不可枚举</span></span><br><span class="line"><span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(ctx, key, &#123;</span><br><span class="line">    <span class="attr">enumerable</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="attr">value</span>: <span class="variable language_">this</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 执行函数，并将执行的结果返回</span></span><br><span class="line"><span class="keyword">return</span> ctx[key](...args)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params">name, age</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>, name, age)</span><br><span class="line">&#125;</span><br><span class="line">fn.<span class="title function_">myCall</span>(&#123;&#125;, <span class="string">&#x27;Cyan&#x27;</span>, <span class="number">27</span>)</span><br></pre></td></tr></table></figure><h2 id="基于-Promise-封装-Ajax"><a href="#基于-Promise-封装-Ajax" class="headerlink" title="基于 Promise 封装 Ajax"></a>基于 Promise 封装 Ajax</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 基于promise封装ajax</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; url 请求地址</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; methods 请求方法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">promise</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">ajax</span>(<span class="params">url, methods = <span class="string">&#x27;get&#x27;</span></span>) &#123;</span><br><span class="line"><span class="comment">// 返回promise实例对象</span></span><br><span class="line"><span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resovle, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">// 创建XMLHttpRequest异步对象</span></span><br><span class="line">    <span class="keyword">const</span> xhr = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>()</span><br><span class="line">    <span class="comment">// 调用open方法，打开url，与服务器建连接</span></span><br><span class="line">    xhr.<span class="title function_">open</span>(url, methods, <span class="literal">true</span>)</span><br><span class="line">    <span class="comment">// 监听状态</span></span><br><span class="line">    xhr.<span class="property">onreadystatechange</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">        <span class="comment">// 表示服务器响应完成，可以获取服务器响应</span></span><br><span class="line">        <span class="keyword">if</span> (xhr.<span class="property">readyState</span> === <span class="number">4</span>) &#123;</span><br><span class="line">            <span class="comment">// 获取成功</span></span><br><span class="line">            <span class="keyword">if</span> (xhr.<span class="property">status</span> === <span class="number">200</span>) &#123;</span><br><span class="line">                <span class="title function_">resovle</span>(xhr.<span class="property">responseText</span>)</span><br><span class="line">                <span class="comment">// 404</span></span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (xhr.<span class="property">status</span> === <span class="number">404</span>) &#123;</span><br><span class="line">                <span class="title function_">reject</span>(<span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&#x27;404&#x27;</span>))</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="title function_">reject</span>(<span class="string">&#x27;请求数据失败&#x27;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="手写-Map"><a href="#手写-Map" class="headerlink" title="手写 Map"></a>手写 Map</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现map方法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback[Function] 执行函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; thisValue 执行 callback 函数时被用作this的值</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Array</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myMap</span> = <span class="keyword">function</span> (<span class="params">callback, thisValue</span>) &#123;</span><br><span class="line"><span class="comment">// 判断参数类型</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;callback is not a function&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 定义一个空数组返回数据</span></span><br><span class="line"><span class="keyword">const</span> result = []</span><br><span class="line"><span class="comment">// 获取该方法的数组本身</span></span><br><span class="line"><span class="keyword">const</span> context = <span class="variable language_">this</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; context.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    <span class="comment">// 循环遍历，执行函数，将结果保存到result中</span></span><br><span class="line">    result[i] = callback.<span class="title function_">call</span>(thisValue, context[i], i, context)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"><span class="keyword">const</span> res = arr.<span class="title function_">myMap</span>(<span class="function"><span class="params">item</span> =&gt;</span> item * <span class="number">2</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(res)</span><br></pre></td></tr></table></figure><h2 id="手写-forEach"><a href="#手写-forEach" class="headerlink" title="手写 forEach"></a>手写 forEach</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现forEach方法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback[Function] 执行函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; thisValue 执行 callback 函数时被用作this的值</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Array</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myForEach</span> = <span class="keyword">function</span> (<span class="params">callback, thisValue</span>) &#123;</span><br><span class="line"><span class="comment">// 判断参数类型</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;callback is not a function&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取该方法的数组本身</span></span><br><span class="line"><span class="keyword">const</span> context = <span class="variable language_">this</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; context.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    <span class="comment">// 循环遍历，执行函数</span></span><br><span class="line">    callback.<span class="title function_">call</span>(thisValue, context[i], i, context)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line">arr.<span class="title function_">myForEach</span>(<span class="function">(<span class="params">item, index</span>) =&gt;</span> &#123;</span><br><span class="line">    arr[index] = item * <span class="number">2</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(arr)</span><br></pre></td></tr></table></figure><h2 id="手写-Filter"><a href="#手写-Filter" class="headerlink" title="手写 Filter"></a>手写 Filter</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现filter方法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback[Function] 执行函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; thisValue 执行 callback 函数时被用作this的值</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Array</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myFilter</span> = <span class="keyword">function</span> (<span class="params">callback, thisValue</span>) &#123;</span><br><span class="line"><span class="comment">// 判断参数类型</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;callback is not a function&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取该方法的数组本身</span></span><br><span class="line"><span class="keyword">const</span> context = <span class="variable language_">this</span></span><br><span class="line"><span class="comment">// 定义一个空数组</span></span><br><span class="line"><span class="keyword">const</span> result = []</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; context.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    <span class="comment">// 循环遍历，执行函数</span></span><br><span class="line">    callback.<span class="title function_">call</span>(thisValue, context[i], i, context) &amp;&amp; result.<span class="title function_">push</span>(context[i])</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"><span class="keyword">const</span> arr2 = arr.<span class="title function_">myFilter</span>(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> item &gt;= <span class="number">2</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(arr2)</span><br></pre></td></tr></table></figure><h2 id="手写-Some"><a href="#手写-Some" class="headerlink" title="手写 Some"></a>手写 Some</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现some方法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback[Function] 执行函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; thisValue 执行 callback 函数时被用作this的值</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Array</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">mySome</span> = <span class="keyword">function</span> (<span class="params">callback, thisValue</span>) &#123;</span><br><span class="line"><span class="comment">// 判断参数类型</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;callback is not a function&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取该方法的数组本身</span></span><br><span class="line"><span class="keyword">const</span> context = <span class="variable language_">this</span></span><br><span class="line"><span class="comment">// 定义一个false值</span></span><br><span class="line"><span class="keyword">let</span> result = <span class="literal">false</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; context.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    <span class="comment">// 循环遍历，执行函数，如果条件符合，则赋值true</span></span><br><span class="line">    callback.<span class="title function_">call</span>(thisValue, context[i], i, context) &amp;&amp; (result = <span class="literal">true</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"><span class="keyword">const</span> arr2 = arr.<span class="title function_">mySome</span>(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> item &gt; <span class="number">2</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(arr2)</span><br></pre></td></tr></table></figure><h2 id="手写-Every"><a href="#手写-Every" class="headerlink" title="手写 Every"></a>手写 Every</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现every方法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback[Function] 执行函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; thisValue 执行 callback 函数时被用作this的值</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">Array</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myEvery</span> = <span class="keyword">function</span> (<span class="params">callback, thisValue</span>) &#123;</span><br><span class="line"><span class="comment">// 判断参数类型</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;callback is not a function&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取该方法的数组本身</span></span><br><span class="line"><span class="keyword">const</span> context = <span class="variable language_">this</span></span><br><span class="line"><span class="comment">// 定义一个true值</span></span><br><span class="line"><span class="keyword">let</span> result = <span class="literal">true</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; context.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    <span class="comment">// 循环遍历，执行函数，如果有一项不符合，则赋值为false</span></span><br><span class="line">    !callback.<span class="title function_">call</span>(thisValue, context[i], i, context) &amp;&amp; (result = <span class="literal">false</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"><span class="keyword">const</span> arr2 = arr.<span class="title function_">myEvery</span>(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> item &gt; <span class="number">2</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(arr2)</span><br></pre></td></tr></table></figure><h2 id="手写-Reduce"><a href="#手写-Reduce" class="headerlink" title="手写 Reduce"></a>手写 Reduce</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现reduce方法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; callback[Function] 执行函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; initValue 执行 callback 函数时被用作第一个参数的值</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="title class_">Array</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">myReduce</span> = <span class="keyword">function</span> (<span class="params">callback, initValue</span>) &#123;</span><br><span class="line"><span class="comment">// 判断参数类型</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;callback is not a function&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取该方法的数组本身</span></span><br><span class="line"><span class="keyword">const</span> context = <span class="variable language_">this</span></span><br><span class="line"><span class="comment">// 判断initValue是否有传值，true代表没传值</span></span><br><span class="line"><span class="keyword">const</span> flag = initValue === <span class="literal">undefined</span></span><br><span class="line"><span class="comment">// 定义一个变量，如果initValue有值就取，没有就取context第一项</span></span><br><span class="line"><span class="keyword">let</span> result = flag ? context[<span class="number">0</span>] : initValue</span><br><span class="line"><span class="comment">// 如果initValue有值就从0开始，否则从1开始</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = (flag ? <span class="number">1</span> : <span class="number">0</span>); i &lt; context.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    <span class="comment">// 循环遍历，执行函数，把结果赋值给上一个值</span></span><br><span class="line">    result = <span class="title function_">callback</span>(result, context[i], i, context)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>]</span><br><span class="line"><span class="keyword">const</span> arr2 = arr.<span class="title function_">myReduce</span>(<span class="function">(<span class="params">perv, current</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> perv + current</span><br><span class="line">&#125;, <span class="number">5</span>)</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(arr2)</span><br></pre></td></tr></table></figure><h2 id="手写-Promise"><a href="#手写-Promise" class="headerlink" title="手写 Promise"></a>手写 Promise</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 实现promise</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; handler[Function] 执行函数,接收两个参数resolve和reject，分别为成功和失败时的回调</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">promise</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">PENDING</span> = <span class="string">&#x27;pending&#x27;</span> <span class="comment">// 初始化状态</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">FULFILLED</span> = <span class="string">&#x27;fulfilled&#x27;</span> <span class="comment">// 成功状态</span></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">REJECTED</span> = <span class="string">&#x27;rejected&#x27;</span> <span class="comment">//失败状态</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyPromise</span> &#123;</span><br><span class="line"><span class="title function_">constructor</span>(<span class="params">handler</span>) &#123;</span><br><span class="line">    <span class="comment">// 初始化状态</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="title function_">initValue</span>()</span><br><span class="line">    <span class="comment">// 接收的参数必须是一个函数</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> handler !== <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;handler is not a function&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 这一步是当promise抛出异常的时候</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 给handler传入两个回调函数并改变this指向</span></span><br><span class="line">        <span class="title function_">handler</span>(<span class="variable language_">this</span>.<span class="property">resolve</span>.<span class="title function_">bind</span>(<span class="variable language_">this</span>), <span class="variable language_">this</span>.<span class="property">reject</span>.<span class="title function_">bind</span>(<span class="variable language_">this</span>))</span><br><span class="line">    &#125; <span class="keyword">catch</span> (e) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="title function_">reject</span>(e)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 初始化 Promise 基本状态</span></span><br><span class="line"><span class="title function_">initValue</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 刚创建的promise状态是pending</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">PromiseState</span> = <span class="variable constant_">PENDING</span></span><br><span class="line">    <span class="comment">// promise的结果</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">PromiseResult</span> = <span class="literal">null</span></span><br><span class="line">    <span class="comment">// 保存成功回调</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">onFulfilledCallbacks</span> = []</span><br><span class="line">    <span class="comment">// 保存失败时回调</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">onRejectedCallbacks</span> = []</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 成功时的回调</span></span><br><span class="line"><span class="title function_">resolve</span>(<span class="params">value</span>) &#123;</span><br><span class="line">    <span class="comment">// 状态不可改变</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">PromiseState</span> !== <span class="variable constant_">PENDING</span>) <span class="keyword">return</span></span><br><span class="line">    <span class="comment">// 成功时的状态</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">PromiseState</span> = <span class="variable constant_">FULFILLED</span></span><br><span class="line">    <span class="comment">// 成功时的结果</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">PromiseResult</span> = value</span><br><span class="line">    <span class="comment">// 执行保存成功回调</span></span><br><span class="line">    <span class="keyword">while</span> (<span class="variable language_">this</span>.<span class="property">onFulfilledCallbacks</span>.<span class="property">length</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">onFulfilledCallbacks</span>.<span class="title function_">shift</span>()(<span class="variable language_">this</span>.<span class="property">PromiseResult</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 失败时的回调</span></span><br><span class="line"><span class="title function_">reject</span>(<span class="params">reason</span>) &#123;</span><br><span class="line">    <span class="comment">// 状态不可改变</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">PromiseState</span> !== <span class="variable constant_">PENDING</span>) <span class="keyword">return</span></span><br><span class="line">    <span class="comment">// 失败时的状态</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">PromiseState</span> = <span class="variable constant_">REJECTED</span></span><br><span class="line">    <span class="comment">// 失败时的结果</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">PromiseResult</span> = reason</span><br><span class="line">    <span class="comment">// 执行保存失败回调</span></span><br><span class="line">    <span class="keyword">while</span> (<span class="variable language_">this</span>.<span class="property">onRejectedCallbacks</span>.<span class="property">length</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">onRejectedCallbacks</span>.<span class="title function_">shift</span>()(<span class="variable language_">this</span>.<span class="property">PromiseResult</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/* </span></span><br><span class="line"><span class="comment">1、then接收两个参数，一个是成功回调，一个是失败回调</span></span><br><span class="line"><span class="comment">2、当Promise状态为fulfilled为成功回调，状态为rejected为失败回调</span></span><br><span class="line"><span class="comment">3、then支持链式调用，下一次then的值受上一次then的返回值影响</span></span><br><span class="line"><span class="comment">4、当有定时器时，需等定时器结束再执行then</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="title function_">then</span>(<span class="params">onFulfilled, onRejected</span>) &#123;</span><br><span class="line">    <span class="comment">// 参数校验，两个回调必须为function</span></span><br><span class="line">    onFulfilled = <span class="keyword">typeof</span> onFulfilled === <span class="string">&#x27;function&#x27;</span> ? onFulfilled : <span class="function"><span class="params">promiseResult</span> =&gt;</span> promiseResult</span><br><span class="line">    onRejected = <span class="keyword">typeof</span> onRejected === <span class="string">&#x27;function&#x27;</span> ? onRejected : <span class="function"><span class="params">reason</span> =&gt;</span> &#123; <span class="keyword">throw</span> (reason) &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// then支持链式调用，模拟返回一个Promise</span></span><br><span class="line">    <span class="keyword">const</span> thenPromise = <span class="keyword">new</span> <span class="title class_">MyPromise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// 使用queueMicrotask执行微任务，让then方法变成微任务</span></span><br><span class="line">        <span class="title function_">queueMicrotask</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="comment">// 定义一个promise函数，用来处理不同状态下的返回值</span></span><br><span class="line">            <span class="keyword">const</span> <span class="title function_">resolvePromise</span> = cb =&gt; &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    <span class="comment">// 拿到上一个promise回调执行的结果</span></span><br><span class="line">                    <span class="keyword">const</span> result = <span class="title function_">cb</span>(<span class="variable language_">this</span>.<span class="property">PromiseResult</span>)</span><br><span class="line">                    <span class="comment">// 判断返回结果是否是一个Promise对象</span></span><br><span class="line">                    <span class="keyword">if</span> (result <span class="keyword">instanceof</span> <span class="title class_">MyPromise</span>) &#123;</span><br><span class="line">                        <span class="comment">// 如果返回值是Promise，只有then知道是成功还是失败</span></span><br><span class="line">                        result.<span class="title function_">then</span>(resolve, reject)</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        <span class="comment">// 如果不是Promise就直接resolve</span></span><br><span class="line">                        <span class="title function_">resolve</span>(result)</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125; <span class="keyword">catch</span> (error) &#123;</span><br><span class="line">                    <span class="comment">// 处理报错</span></span><br><span class="line">                    <span class="title function_">reject</span>(err)</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(error)</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 判断 Promise 状态，执行不同的操作</span></span><br><span class="line">            <span class="keyword">switch</span> (<span class="variable language_">this</span>.<span class="property">PromiseState</span>) &#123;</span><br><span class="line">                <span class="comment">// 当状态为fulfilled时为成功时的回调</span></span><br><span class="line">                <span class="keyword">case</span> <span class="attr">FULFILLED</span>:</span><br><span class="line">                    <span class="comment">// 执行成功函数</span></span><br><span class="line">                    <span class="title function_">resolvePromise</span>(onFulfilled)</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="comment">// 当状态为rejected时为失败时的回调</span></span><br><span class="line">                <span class="keyword">case</span> <span class="attr">REJECTED</span>:</span><br><span class="line">                    <span class="comment">// 执行失败函数</span></span><br><span class="line">                    <span class="title function_">resolvePromise</span>(onRejected)</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="comment">// 当状态还未改变时，也就是pending时</span></span><br><span class="line">                <span class="keyword">case</span> <span class="attr">PENDING</span>:</span><br><span class="line">                    <span class="comment">// 如果状态待定，暂时保存两个回调</span></span><br><span class="line">                    <span class="variable language_">this</span>.<span class="property">onFulfilledCallbacks</span>.<span class="title function_">push</span>(resolvePromise.<span class="title function_">bind</span>(<span class="variable language_">this</span>, onFulfilled))</span><br><span class="line">                    <span class="variable language_">this</span>.<span class="property">onRejectedCallbacks</span>.<span class="title function_">push</span>(resolvePromise.<span class="title function_">bind</span>(<span class="variable language_">this</span>, onRejected))</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> thenPromise</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// catch方法其实就是then方法失败回调函数的语法糖</span></span><br><span class="line"><span class="keyword">catch</span>(onRejected) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="title function_">then</span>(<span class="literal">undefined</span>, onRejected)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// finally方法，不管Promise状态是失败还是成功都会执行</span></span><br><span class="line"><span class="title function_">finally</span>(<span class="params">callback</span>) &#123;</span><br><span class="line">    <span class="title function_">queueMicrotask</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        callback.<span class="title function_">call</span>(<span class="variable language_">this</span>)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="title class_">MyPromise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;MyPromise立即执行&#x27;</span>)</span><br><span class="line">    <span class="title function_">resolve</span>(<span class="string">&#x27;100&#x27;</span>)</span><br><span class="line">&#125;)</span><br><span class="line">p.<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> res, <span class="function"><span class="params">reason</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;then是微任务&#x27;</span>)</span><br><span class="line">&#125;).<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(res * <span class="number">2</span>)</span><br><span class="line">    <span class="keyword">return</span> res * <span class="number">2</span></span><br><span class="line">&#125;).<span class="title function_">then</span>(<span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(res * <span class="number">2</span>)</span><br><span class="line">&#125;)</span><br><span class="line">p.<span class="title function_">catch</span>(<span class="function"><span class="params">err</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(err)</span><br><span class="line">&#125;)</span><br><span class="line">p.<span class="title function_">finally</span>(<span class="function">(<span class="params">a, b</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;不管什么状态都会执行&#x27;</span>)</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 同步任务</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="number">3</span>)</span><br></pre></td></tr></table></figure><h2 id="扁平数组转成树形数组"><a href="#扁平数组转成树形数组" class="headerlink" title="扁平数组转成树形数组"></a>扁平数组转成树形数组</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 扁平数组转成树形数组</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; source 源数据</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; id,parentId,children</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">treeData</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">transformTreeData</span> = (<span class="params">source,id,parentId,children</span>)=&gt;&#123;</span><br><span class="line">    <span class="comment">// 判断原数组是否是数组</span></span><br><span class="line">    <span class="keyword">if</span>(!<span class="title class_">Array</span>.<span class="title function_">isArray</span>(source))&#123;</span><br><span class="line">        <span class="keyword">return</span> []</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 深克隆一份源数据</span></span><br><span class="line">    <span class="keyword">let</span> cloneData = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="title class_">JSON</span>.<span class="title function_">stringify</span>(source))</span><br><span class="line">    <span class="comment">// 循环过滤，并添加children属性</span></span><br><span class="line">    <span class="keyword">return</span> cloneData.<span class="title function_">filter</span>(<span class="function"><span class="params">father</span>=&gt;</span>&#123;</span><br><span class="line">        <span class="comment">// 返回每一级的子级数组</span></span><br><span class="line">        <span class="keyword">let</span> branceChild = cloneData.<span class="title function_">filter</span>(<span class="function"><span class="params">child</span>=&gt;</span>father[id] == child[parentId])</span><br><span class="line">        <span class="comment">// 如果存在子级，给父级添加一个children属性并赋值</span></span><br><span class="line">        branceChild.<span class="property">length</span> &gt; <span class="number">0</span>?father[children] = <span class="attr">branceChild</span>:<span class="string">&#x27;&#x27;</span></span><br><span class="line">        <span class="comment">// 返回第一层数据</span></span><br><span class="line">        <span class="keyword">return</span> father[parentId] == <span class="number">0</span></span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">id</span>:<span class="number">1</span>,</span><br><span class="line">        <span class="attr">parentId</span>:<span class="number">0</span>,</span><br><span class="line">        <span class="attr">name</span>:<span class="string">&#x27;一级-1&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">id</span>:<span class="number">2</span>,</span><br><span class="line">        <span class="attr">parentId</span>:<span class="number">0</span>,</span><br><span class="line">        <span class="attr">name</span>:<span class="string">&#x27;一级-2&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">id</span>:<span class="number">3</span>,</span><br><span class="line">        <span class="attr">parentId</span>:<span class="number">0</span>,</span><br><span class="line">        <span class="attr">name</span>:<span class="string">&#x27;一级-3&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">id</span>:<span class="number">4</span>,</span><br><span class="line">        <span class="attr">parentId</span>:<span class="number">1</span>,</span><br><span class="line">        <span class="attr">name</span>:<span class="string">&#x27;二级-1&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">id</span>:<span class="number">5</span>,</span><br><span class="line">        <span class="attr">parentId</span>:<span class="number">4</span>,</span><br><span class="line">        <span class="attr">name</span>:<span class="string">&#x27;三级-1&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">id</span>:<span class="number">6</span>,</span><br><span class="line">        <span class="attr">parentId</span>:<span class="number">2</span>,</span><br><span class="line">        <span class="attr">name</span>:<span class="string">&#x27;二级-2&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">id</span>:<span class="number">7</span>,</span><br><span class="line">        <span class="attr">parentId</span>:<span class="number">3</span>,</span><br><span class="line">        <span class="attr">name</span>:<span class="string">&#x27;二级-3&#x27;</span></span><br><span class="line">    &#125;,</span><br><span class="line">]</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">transformTreeData</span>(arr,<span class="string">&#x27;id&#x27;</span>,<span class="string">&#x27;parentId&#x27;</span>,<span class="string">&#x27;children&#x27;</span>))</span><br></pre></td></tr></table></figure><h2 id="树形数组转成扁平数组"><a href="#树形数组转成扁平数组" class="headerlink" title="树形数组转成扁平数组"></a>树形数组转成扁平数组</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 树形数组转成扁平数组</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> &#123;<span class="type">*</span>&#125; source 源数据</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> <span class="variable">treeData</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">transformFlatData</span> = (<span class="params">source</span>) =&gt; &#123;</span><br><span class="line">    <span class="comment">// 判断原数组是否是数组</span></span><br><span class="line">    <span class="keyword">if</span> (!<span class="title class_">Array</span>.<span class="title function_">isArray</span>(source)) &#123;</span><br><span class="line">        <span class="keyword">return</span> []</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 定义一个结果集</span></span><br><span class="line">    <span class="keyword">let</span> result = []</span><br><span class="line">    <span class="comment">// 循环遍历</span></span><br><span class="line">    source.<span class="title function_">forEach</span>(<span class="function"><span class="params">item</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// 将每一项插入result</span></span><br><span class="line">        result.<span class="title function_">push</span>(item)</span><br><span class="line">        <span class="comment">// 判断是否有子级，有则递归遍历</span></span><br><span class="line">        item.<span class="property">children</span> &amp;&amp; result.<span class="title function_">push</span>(...<span class="title function_">transformFlatData</span>(item.<span class="property">children</span>))</span><br><span class="line">        <span class="comment">// 删除每一项的children</span></span><br><span class="line">        <span class="keyword">delete</span> item.<span class="property">children</span></span><br><span class="line">    &#125;)</span><br><span class="line">    <span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">1</span>,</span><br><span class="line">        <span class="attr">parentId</span>: <span class="number">0</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;一级-1&#x27;</span>,</span><br><span class="line">        <span class="attr">children</span>: [</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="attr">id</span>: <span class="number">2</span>,</span><br><span class="line">                <span class="attr">parentId</span>: <span class="number">1</span>,</span><br><span class="line">                <span class="attr">name</span>: <span class="string">&#x27;一级-2&#x27;</span></span><br><span class="line">            &#125;,</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="attr">id</span>: <span class="number">3</span>,</span><br><span class="line">                <span class="attr">parentId</span>: <span class="number">1</span>,</span><br><span class="line">                <span class="attr">name</span>: <span class="string">&#x27;一级-3&#x27;</span>,</span><br><span class="line">                <span class="attr">children</span>: [</span><br><span class="line">                    &#123;</span><br><span class="line">                        <span class="attr">id</span>: <span class="number">4</span>,</span><br><span class="line">                        <span class="attr">parentId</span>: <span class="number">3</span>,</span><br><span class="line">                        <span class="attr">name</span>: <span class="string">&#x27;三级-1&#x27;</span></span><br><span class="line">                    &#125;,</span><br><span class="line">                    &#123;</span><br><span class="line">                        <span class="attr">id</span>: <span class="number">5</span>,</span><br><span class="line">                        <span class="attr">parentId</span>: <span class="number">5</span>,</span><br><span class="line">                        <span class="attr">name</span>: <span class="string">&#x27;三级-2&#x27;</span></span><br><span class="line">                    &#125;</span><br><span class="line">                ]</span><br><span class="line">            &#125;</span><br><span class="line">        ]</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">]</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">transformFlatData</span>(arr))</span><br></pre></td></tr></table></figure></article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者:</span> <span class="post-copyright-info"><a href="https://xmwpro.com">Cyan</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接:</span> <span class="post-copyright-info"><a href="https://xmwpro.com/post/2610edc0.html">https://xmwpro.com/post/2610edc0.html</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明:</span> <span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="external nofollow noreferrer" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://xmwpro.com" target="_blank">Cyan</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/JavaScript/"><span class="tags-punctuation">#</span><span class="tags-name">JavaScript</span><sup>4</sup></a><a class="post-meta__tags" href="/tags/%E9%9D%A2%E8%AF%95/"><span class="tags-punctuation">#</span><span class="tags-name">面试</span><sup>2</sup></a></div><div class="post_share"><div class="social-share" data-image="https://ali-oss.xmwpro.com/global/avatar.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/share.min.css" media="print" onload='this.media="all"'><script src="https://ali-oss.xmwpro.com/cdn/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="https://ali-oss.xmwpro.com/global/wx-pay.jpeg" rel="external nofollow noreferrer" target="_blank"><img class="post-qr-code-img" src="" data-lazy-src="https://ali-oss.xmwpro.com/global/wx-pay.jpeg" alt="微信"></a><div class="post-qr-code-desc">微信</div></li><li class="reward-item"><a href="https://ali-oss.xmwpro.com/global/zfb-pay.jpeg" rel="external nofollow noreferrer" target="_blank"><img class="post-qr-code-img" src="" data-lazy-src="https://ali-oss.xmwpro.com/global/zfb-pay.jpeg" alt="支付宝"></a><div class="post-qr-code-desc">支付宝</div></li></ul></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/post/fe58496d.html" title="大环境下失业引发的思考"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover31.jpg" onerror='onerror=null,src="/img/404.jpg"' alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">大环境下失业引发的思考</div></div></a></div><div class="next-post pull-right"><a href="/post/65e63605.html" title="vue-router钩子函数和具体的执行流程"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover23.jpg" onerror='onerror=null,src="/img/404.jpg"' alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">vue-router钩子函数和具体的执行流程</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list swiper"><div class="swiper-wrapper"><div class="swiper-slide related-item"><a href="/post/185611d5.html" title="JavaScript 常见算法"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover2.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-08-18</div><div class="title">JavaScript 常见算法</div></div></a></div><div class="swiper-slide related-item"><a href="/post/65e63605.html" title="vue-router钩子函数和具体的执行流程"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover38.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-08-17</div><div class="title">vue-router钩子函数和具体的执行流程</div></div></a></div><div class="swiper-slide related-item"><a href="/post/b7a80595.html" title="大厂面试经典算法题"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover39.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-08-20</div><div class="title">大厂面试经典算法题</div></div></a></div><div class="swiper-slide related-item"><a href="/post/64634f2a.html" title="个人前端面试心得-2022.08"><img class="cover" src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover37.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-08-24</div><div class="title">个人前端面试心得-2022.08</div></div></a></div></div><div class="related-swiper-scrollbar"></div></div></div><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i> <span>评论</span></div><div class="comment-tips">您无需删除空行，直接评论以获取最佳展示效果</div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div></div><div class="barrageswiper"><div class="swiper"><div class="swiper-wrapper"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="card-info-my"><div class="card-info-my-avatar"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/avatar.jpg" onerror='this.onerror=null,this.src="/img/friend_404.gif"' alt="avatar"></div><div class="card-info-my-name"><div class="card-info-my-name-welcome"></div><div class="card-info-my-name-text">谢明伟</div></div></div><div class="card-info-content"><b>记录学习、生活和有趣的事</b></div><div class="card-info-announcement">好好吃饭🍣 好好睡觉💤 敲敲代码💻 谈谈恋爱💑</div><div class="card-info-social"><div class="card-info-social-icon"><a class="social-icon" href="https://github.com/Cyan-Xmw" rel="external nofollow noreferrer" target="_blank" title="Github"><i class="iconfont cyan-github-fill"></i></a></div><a class="card-info-social-more" href="/about/"><i class="fas fa-circle-chevron-right"></i><span class="card-info-social-more-text">了解更多</span></a></div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%89%8D%E8%A8%80"><span class="toc-number">1.</span> <span class="toc-text">前言</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%98%B2%E6%8A%96%E5%87%BD%E6%95%B0"><span class="toc-number">2.</span> <span class="toc-text">防抖函数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%8A%82%E6%B5%81%E5%87%BD%E6%95%B0"><span class="toc-number">3.</span> <span class="toc-text">节流函数</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%87%BD%E6%95%B0%E6%9F%AF%E9%87%8C%E5%8C%96"><span class="toc-number">4.</span> <span class="toc-text">函数柯里化</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B7%B1%E6%8B%B7%E8%B4%9D"><span class="toc-number">5.</span> <span class="toc-text">深拷贝</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Instanceof-%E5%AE%9E%E7%8E%B0"><span class="toc-number">6.</span> <span class="toc-text">Instanceof 实现</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Object-create-%E5%AE%9E%E7%8E%B0"><span class="toc-number">7.</span> <span class="toc-text">Object.create 实现</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#New-%E5%AE%9E%E7%8E%B0"><span class="toc-number">8.</span> <span class="toc-text">New 实现</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-Bind"><span class="toc-number">9.</span> <span class="toc-text">手写 Bind</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-Apply"><span class="toc-number">10.</span> <span class="toc-text">手写 Apply</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-Call"><span class="toc-number">11.</span> <span class="toc-text">手写 Call</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9F%BA%E4%BA%8E-Promise-%E5%B0%81%E8%A3%85-Ajax"><span class="toc-number">12.</span> <span class="toc-text">基于 Promise 封装 Ajax</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-Map"><span class="toc-number">13.</span> <span class="toc-text">手写 Map</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-forEach"><span class="toc-number">14.</span> <span class="toc-text">手写 forEach</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-Filter"><span class="toc-number">15.</span> <span class="toc-text">手写 Filter</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-Some"><span class="toc-number">16.</span> <span class="toc-text">手写 Some</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-Every"><span class="toc-number">17.</span> <span class="toc-text">手写 Every</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-Reduce"><span class="toc-number">18.</span> <span class="toc-text">手写 Reduce</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%8B%E5%86%99-Promise"><span class="toc-number">19.</span> <span class="toc-text">手写 Promise</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%89%81%E5%B9%B3%E6%95%B0%E7%BB%84%E8%BD%AC%E6%88%90%E6%A0%91%E5%BD%A2%E6%95%B0%E7%BB%84"><span class="toc-number">20.</span> <span class="toc-text">扁平数组转成树形数组</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%A0%91%E5%BD%A2%E6%95%B0%E7%BB%84%E8%BD%AC%E6%88%90%E6%89%81%E5%B9%B3%E6%95%B0%E7%BB%84"><span class="toc-number">21.</span> <span class="toc-text">树形数组转成扁平数组</span></a></li></ol></div></div><div class="card-widget card-recent-post"><div class="aside-list"><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/a109015f.html" title="TS 中的类型验算,高级通用 API 实现"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover17.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="TS 中的类型验算,高级通用 API 实现"></a><div class="content"><a class="title" href="/post/a109015f.html" title="TS 中的类型验算,高级通用 API 实现">TS 中的类型验算,高级通用 API 实现</a><time datetime="2023-06-26T15:26:24.000Z" title="发表于 2023-06-26 15:26:24">2023-06-26</time></div></div><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/1ce87d42.html" title="使用 sort-imports 排序规则美化头部 import 代码"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover22.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="使用 sort-imports 排序规则美化头部 import 代码"></a><div class="content"><a class="title" href="/post/1ce87d42.html" title="使用 sort-imports 排序规则美化头部 import 代码">使用 sort-imports 排序规则美化头部 import 代码</a><time datetime="2023-06-06T15:39:24.000Z" title="发表于 2023-06-06 15:39:24">2023-06-06</time></div></div><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/b3e4ecaf.html" title="Vue 中如何监控用户网络状态"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover18.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="Vue 中如何监控用户网络状态"></a><div class="content"><a class="title" href="/post/b3e4ecaf.html" title="Vue 中如何监控用户网络状态">Vue 中如何监控用户网络状态</a><time datetime="2023-05-22T16:08:02.000Z" title="发表于 2023-05-22 16:08:02">2023-05-22</time></div></div><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/50b97751.html" title="在 vite 中使用 glob 实现约定式路由"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover43.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="在 vite 中使用 glob 实现约定式路由"></a><div class="content"><a class="title" href="/post/50b97751.html" title="在 vite 中使用 glob 实现约定式路由">在 vite 中使用 glob 实现约定式路由</a><time datetime="2023-05-16T16:35:16.000Z" title="发表于 2023-05-16 16:35:16">2023-05-16</time></div></div><div class="aside-list-item no-cover"><a class="thumbnail" href="/post/7b74bd27.html" title="基于 React + Nest 的后台应用"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/posts/post_cover45.jpg" onerror='this.onerror=null,this.src="/img/404.jpg"' alt="基于 React + Nest 的后台应用"></a><div class="content"><a class="title" href="/post/7b74bd27.html" title="基于 React + Nest 的后台应用">基于 React + Nest 的后台应用</a><time datetime="2023-04-18T10:39:21.000Z" title="发表于 2023-04-18 10:39:21">2023-04-18</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="site-business"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/business.svg" alt="Cyan"></div><div class="site-services"><div class="site-services-link"><a class="site-services-link-item" href="https://www.aliyun.com/" rel="external nofollow noreferrer" target="_blank" title="阿里云提供cdn加速和云存储服务"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/aliyun.svg" alt="阿里云"></a><a class="site-services-link-item" href="https://www.foreverblog.cn/blog/4240.html/" rel="external nofollow noreferrer" target="_blank" title="十年之约虫洞服务"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/foreverblog-zh.svg" alt="十年之约"></a><a class="site-services-link-item" href="https://beian.miit.gov.cn/" rel="external nofollow noreferrer" target="_blank" title="粤ICP备2023007649号"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/icp.png" alt="粤ICP备2023007649号"><span>粤ICP备2023007649号</span></a><a class="site-services-link-item" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=44030402006264" rel="external nofollow noreferrer" target="_blank" title="粤公网安备44030402006264号"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/security.png" alt="粤公网安备44030402006264号"><span>粤公网安备44030402006264号</span></a></div></div><div class="footer_custom_text"><p style="margin:0"><a target="_blank" rel="noopener external nofollow noreferrer" href="https://hexo.io/" style="margin-inline:5px"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/hexo.svg" alt="博客框架 Hexo"></a><a target="_blank" rel="noopener external nofollow noreferrer" href="https://butterfly.js.org/" style="margin-inline:5px"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/Butterfly.svg" alt="主题 Butterfly"></a><a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/" style="margin-inline:5px"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/github.svg" alt="本站托管于 Github"></a><a target="_blank" rel="noopener external nofollow noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/" style="margin-inline:5px"><img src="" data-lazy-src="https://ali-oss.xmwpro.com/global/copyright.svg" alt="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可"></a></p></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="to_comment" type="button" title="直达评论" onclick='cyan.scrollTo("#post-comment")'><i class="fas fa-comments"></i></button><button id="toggle-barrage" type="button" title="开启/关闭弹幕" onclick="cyan.switchCommentBarrage()"><i class="iconfont cyan-barrage"></i></button><button id="toggle-music" type="button" title="播放/暂停音乐" onclick="cyan.musicToggle()"><i class="fas fa-solid fa-music"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div id="nav-music"><div id="nav-music-hoverTips" onclick="cyan.musicToggle()">播放音乐</div><meting-js id="6589687940" server="netease" type="playlist" mutex="true" preload="none" theme="var(--cyan-theme-color)" data-lrctype="0" order="random"></meting-js></div><div id="algolia-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">全局搜索</span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="search-wrap"><div id="algolia-search-input"></div><div id="algolia-search-results"><div id="algolia-hits"></div><div id="algolia-pagination"></div><div id="algolia-info"><div class="algolia-stats"></div><div class="algolia-poweredBy"></div></div></div></div></div><div id="search-mask"></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/fancybox.umd.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/instantclick-1.2.2.js" type="module"></script><script src="https://ali-oss.xmwpro.com/cdn/js/lazyload.iife.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/snackbar.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/algoliasearch-lite.umd.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/instantsearch.production.min.js"></script><script src="/js/search/algolia.js"></script><div class="js-pjax"><script>(()=>{const o=()=>{twikoo.init(Object.assign({el:"#twikoo-wrap",envId:"https://twikoo.xmwpro.com/",region:"",onCommentLoaded:function(){btf.loadLightbox(document.querySelectorAll("#twikoo .tk-content img:not(.tk-owo-emotion)"))}},null)),GLOBAL_CONFIG_SITE.isPost&&(()=>{const o=document.getElementById("twikoo-count");o&&twikoo.getCommentsCount({envId:"https://twikoo.xmwpro.com/",region:"",urls:[window.location.pathname],includeReply:!1}).then((function(t){o.innerText=t[0].count})).catch((function(o){console.error(o)}))})()},t=()=>{"object"!=typeof twikoo?getScript("https://ali-oss.xmwpro.com/cdn/js/twikoo.all.min.js").then(o):setTimeout(o,0)};t()})()</script></div><script>window.addEventListener("load",(()=>{const e=e=>{let t="";if(e.length)for(let n=0;n<e.length;n++){t+="<div class='aside-list-item'>";{const a="data-lazy-src";t+=`<a href='${e[n].url}' class='thumbnail'><img ${a}='${e[n].avatar}' alt='${e[n].nick}'></a>`}t+=`<div class='content'>\n        <a class='comment' href='${e[n].url}' title='${e[n].content}'>${e[n].content}</a>\n        <div class='name'><span>${e[n].nick} / </span><time datetime="${e[n].date}">${btf.diffDate(e[n].date,!0)}</time></div>\n        </div></div>`}else t+="没有评论";let n=document.querySelector("#card-newest-comments .aside-list");n.innerHTML=t,window.lazyLoadInstance&&window.lazyLoadInstance.update(),window.pjax&&window.pjax.refresh(n)},t=()=>{if(document.querySelector("#card-newest-comments .aside-list")){const t=saveToLocal.get("twikoo-newest-comments");t?e(JSON.parse(t)):(()=>{const t=()=>{twikoo.getRecentComments({envId:"https://twikoo.xmwpro.com/",region:"",pageSize:6,includeReply:!0}).then((function(t){const n=t.map((e=>{return{content:(t=e.comment,""===t||(t=(t=(t=(t=t.replace(/<img.*?src="(.*?)"?[^\>]+>/gi,"[图片]")).replace(/<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi,"[链接]")).replace(/<pre><code>.*?<\/pre>/gi,"[代码]")).replace(/<[^>]+>/g,"")).length>150&&(t=t.substring(0,150)+"..."),t),avatar:e.avatar,nick:e.nick,url:e.url+"#"+e.id,date:new Date(e.created).toISOString()};var t}));saveToLocal.set("twikoo-newest-comments",JSON.stringify(n),10/1440),e(n)})).catch((function(e){document.querySelector("#card-newest-comments .aside-list").innerHTML="无法获取评论，请确认相关配置是否正确"}))};"object"==typeof twikoo?t():getScript("https://ali-oss.xmwpro.com/cdn/js/twikoo.all.min.js").then(t)})()}};t(),document.addEventListener("pjax:complete",t)}))</script><script async data-pjax src="/js/custom.js"></script><script async data-pjax src="/js/cascade.js"></script><script defer data-pjax src="//at.alicdn.com/t/c/font_3348168_pqjhlyxfz9r.js"></script><script async src="/js/commentBarrage.js"></script><script async data-pjax src="/js/sky.js"></script><script src="https://sdk.51.la/perf/js-sdk-perf.min.js" crossorigin="anonymous"></script><script>LA.init({id:"JxZKIeqz3SoTqaVu",ck:"JxZKIeqz3SoTqaVu"})</script><script>(new LingQue.Monitor).init({id:"JxZKIeqz3SoTqaVu",sendSuspicious:!0})</script><script src="/cyan/random.js"></script><script>let tianliGPT_postSelector="#post #article-container",tianliGPT_key="nWP7yQwRFXvk0piPhO2w"</script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/tianli_gpt.js"></script><link rel="stylesheet" href="https://ali-oss.xmwpro.com/cdn/css/APlayer.min.css" media="print" onload='this.media="all"'><script src="https://ali-oss.xmwpro.com/cdn/js/APlayer.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/Meting.min.js"></script><script src="https://ali-oss.xmwpro.com/cdn/js/pjax.min.js"></script><script>let pjaxSelectors=["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"];var pjax=new Pjax({elements:'a:not([target="_blank"]):not([href="/tags/"]):not([href="/categories/"]):not([href="/analysis/"]):not([href="/fcircle/"])',selectors:pjaxSelectors,cacheBust:!1,analytics:!0,scrollRestoration:!1});document.addEventListener("pjax:send",(function(){if(window.tocScrollFn&&window.removeEventListener("scroll",window.tocScrollFn),window.scrollCollect&&window.removeEventListener("scroll",scrollCollect),document.getElementById("rightside").style.cssText="opacity: ''; transform: ''",window.aplayers)for(let e=0;e<window.aplayers.length;e++)window.aplayers[e].options.fixed||window.aplayers[e].destroy();"object"==typeof typed&&typed.destroy();const e=document.body.classList;e.contains("read-mode")&&e.remove("read-mode"),"object"==typeof disqusjs&&disqusjs.destroy()})),document.addEventListener("pjax:complete",(function(){window.refreshFn(),document.querySelectorAll("script[data-pjax]").forEach((e=>{const t=document.createElement("script"),o=e.text||e.textContent||e.innerHTML||"";Array.from(e.attributes).forEach((e=>t.setAttribute(e.name,e.value))),t.appendChild(document.createTextNode(o)),e.parentNode.replaceChild(t,e)})),GLOBAL_CONFIG.islazyload&&window.lazyLoadInstance.update(),"function"==typeof chatBtnFn&&chatBtnFn(),"function"==typeof panguInit&&panguInit(),"function"==typeof gtag&&gtag("config","G-2P0LMHZNDD",{page_path:window.location.pathname}),"object"==typeof _hmt&&_hmt.push(["_trackPageview",window.location.pathname]),"function"==typeof loadMeting&&document.getElementsByClassName("aplayer").length&&loadMeting(),"object"==typeof Prism&&Prism.highlightAll()})),document.addEventListener("pjax:error",(e=>{404===e.request.status&&pjax.loadUrl("/404.html")}))</script></div><script>var fdata={apiurl:"https://friend-api.xmwpro.com/",initnumber:30,stepnumber:30,error_img:"https://npm.elemecdn.com/akilar-candyassets/image/404.gif"};localStorage.setItem("fdatalist",JSON.stringify(fdata))</script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/fetch-friend.js"></script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/random-friends-post.js"></script><script async src="//at.alicdn.com/t/c/font_3344355_6og082zqzfd.js"></script><div class="js-pjax"><script async>for(var arr=document.getElementsByClassName("recent-post-item"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration",""),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("bbTimeList"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration",""),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("card-widget"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration",""),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("category-in-bar"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration",""),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("bber-item"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__fadeInUp"),arr[i].setAttribute("data-wow-duration","1.5s"),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script><script async>for(var arr=document.getElementsByClassName("statistics-item"),i=0;i<arr.length;i++)arr[i].classList.add("wow"),arr[i].classList.add("animate__zoomIn"),arr[i].setAttribute("data-wow-duration","1.5s"),arr[i].setAttribute("data-wow-delay",""),arr[i].setAttribute("data-wow-offset","20"),arr[i].setAttribute("data-wow-iteration","")</script></div><script defer src="https://ali-oss.xmwpro.com/cdn/js/wow.min.js"></script><script defer src="https://ali-oss.xmwpro.com/cdn/js/wow_init.js"></script><script data-pjax src="https://ali-oss.xmwpro.com/cdn/js/gitcalendar.js"></script><script data-pjax>function gitcalendar_injector_config(){document.getElementById("recent-posts").insertAdjacentHTML("afterbegin",'<div class="recent-post-item" id="gitcalendarBar" style="width:100%;height:auto;padding:10px;"><style>#git_container{min-height: 280px}@media screen and (max-width:650px) {#git_container{min-height: 0px}}</style><div id="git_loading" style="width:10%;height:100%;margin:0 auto;display: block;"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50" xml:space="preserve"><path fill="#d0d0d0" d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" transform="rotate(275.098 25 25)"><animatetransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="0.6s" repeatCount="indefinite"></animatetransform></path></svg><style>#git_container{display: none;}</style></div><div id="git_container"></div></div>'),console.log("已挂载gitcalendar")}document.getElementById("recent-posts")&&"/"===location.pathname&&(gitcalendar_injector_config(),GitCalendarInit("https://github-calendar.xmwpro.com/api?Cyan-Xmw",["#e3f2fd","#bbdefb","#90caf9","#64b5f6","#42a5f5","#2196f3","#1e88e5","#1976d2","#1565c0","#0d47a1","#425AEF"],"Cyan-Xmw"))</script></body></html>